/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package fr.univnantes.alma.arbres;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Vector;

/**
 *
 * @author judu
 */
class ArbreTMIteratorDFS<T> implements Iterator<Noeud<T>> {
    
    private Vector<NoeudTM<T>> arbre;
    private LinkedList<NoeudTM<T>> enVisite;
    private final int arite;

    public ArbreTMIteratorDFS(Vector<NoeudTM<T>> arbre, int arite) {
        this.arbre = arbre;
        this.enVisite = new LinkedList<NoeudTM<T>>();
        this.enVisite.addLast(this.arbre.get(0));
        this.arite = arite;

        //System.out.println("Création iterator, taille du vector "+this.arbre.size());
    }


    private void setUpNext(NoeudTM<T> current){
        //System.out.println("SetUpNext("+current.toString()+")");

        LinkedList<NoeudTM<T>> ll = this.getListeFils(current);

        //if(ll != null) System.out.println("SetUpNext().ll = "+ll.toString());

        if(ll != null){
            this.enVisite.addAll(ll);
        }
    }

    /**
     *
     * @param n
     * @return La liste des Fils d'un noeud passé en paramètre.
     */
    private LinkedList<NoeudTM<T>> getListeFils(NoeudTM<T> n){
        if(n == null) return null;
        if(n.getIndex()*this.arite+1 >= this.arbre.size()) return null;

        LinkedList<NoeudTM<T>> li = new LinkedList<NoeudTM<T>>();


        //System.out.println("getListeFils "+n.toString()+" (position "+n.getIndex()+")");

        int pos = 1;
        int in = n.getIndex()*this.arite+pos;
        do {
            //System.out.println("Valeur de in : "+in);
            NoeudTM<T> tmp = null;
            try {
                tmp = this.arbre.get(in);
            } catch(Exception e){
                System.out.println(e.getMessage());
            }
            
            if(tmp != null){
                li.addFirst(tmp);
            }
            ++pos;
            ++in;
        } while (pos <= this.arite);

        return (li.isEmpty())? null:li;
    }


    public boolean hasNext() {
        return !(this.enVisite.isEmpty());
    }

    public Noeud<T> next() throws NoSuchElementException {
        if(!this.hasNext()) throw new NoSuchElementException("Terminus de l'arbre, vérifiez en sortant que vous n'oubliez aucun bagage.");
        NoeudTM<T> current = this.enVisite.removeLast();
        this.setUpNext(current);
        return current.autoCast();
    }

    public void remove() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

}
